package com.smartleanx.module.hrm.controller.admin.payrollapproverecord;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.smartleanx.framework.common.enums.BizTypeEnum;
import com.smartleanx.framework.common.pojo.CommonResult;
import com.smartleanx.framework.common.pojo.PageResult;
import com.smartleanx.framework.common.util.collection.CollectionUtils;
import com.smartleanx.framework.customfield.core.service.CustomFieldDataService;
import com.smartleanx.framework.customfield.core.service.bo.CustomFieldDataListReqBO;
import com.smartleanx.framework.customfield.core.service.bo.CustomFieldDataRespBO;
import com.smartleanx.module.hrm.controller.admin.payrollapproverecord.vo.PayrollApproveRecordDetailPageReqVO;
import com.smartleanx.module.hrm.dal.dataobject.employee.EmployeeDO;
import com.smartleanx.module.hrm.dal.dataobject.payroll.PayrollDO;
import com.smartleanx.module.hrm.dal.dataobject.payrollapproverecord.PayrollApproveRecordDO;
import com.smartleanx.module.hrm.dal.dataobject.payrollapproverecord.PayrollApproveRecordDetailDO;
import com.smartleanx.module.hrm.eums.employee.EmployeeStatusEnum;
import com.smartleanx.module.hrm.eums.payroll.PayrollStateEnum;
import com.smartleanx.module.hrm.intergration.CustomFieldServiceProvider;
import com.smartleanx.module.hrm.service.employee.EmployeeService;
import com.smartleanx.module.hrm.service.payroll.PayrollService;
import com.smartleanx.module.hrm.service.payrollapproverecord.PayrollApproveRecordDetailService;
import com.smartleanx.module.hrm.service.payrollapproverecord.PayrollApproveRecordService;
import com.smartleanx.module.system.api.customfield.dto.CustomFieldReqDTO;
import com.smartleanx.module.system.api.customfield.dto.CustomFieldRespDTO;
import com.smartleanx.module.system.enums.customfield.CustomFieldLabelEnum;
import com.smartleanx.module.system.enums.customfield.CustomFieldTypeEnum;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.math.BigDecimal;
import java.util.*;

import static com.smartleanx.framework.common.pojo.CommonResult.success;

@Tag(name = "管理后台 - 薪资审批记录详情")
@RestController
@RequestMapping("/hrm/payroll-approve-record-detail")
@Validated
public class PayrollApproveRecordDetailController {

    @Resource
    private PayrollApproveRecordService payrollApproveRecordService;

    @Resource
    private PayrollService payrollService;

    @Resource
    private PayrollApproveRecordDetailService payrollApproveRecordDetailService;

    @Resource
    private CustomFieldDataService customFieldDataService;

    @Resource
    private EmployeeService employeeService;

    @Resource
    private CustomFieldServiceProvider customFieldServiceProvider;

    @GetMapping("/page")
    @Operation(summary = "获得薪资审批记录详情分页")
    @PreAuthorize("@ss.hasPermission('hrm:payroll-approve-record-detail:query')")
    public CommonResult<PageResult<Map<String, CustomFieldDataRespBO>>> getPayrollApproveRecordDetailPage(@Valid PayrollApproveRecordDetailPageReqVO pageReqVO) {
        PageResult<PayrollApproveRecordDetailDO> pageResult = payrollApproveRecordDetailService.getDetailPage(pageReqVO);
        PayrollApproveRecordDO record = payrollApproveRecordService.getRecord(pageReqVO.getPayrollApproveRecordId());
        PayrollDO payroll = payrollService.getPayroll(record.getPayrollId());
        if(Objects.isNull(payroll)){
            return success(new PageResult<>(Collections.emptyList(), pageResult.getTotal()));
        }
        List<PayrollApproveRecordDetailDO> detailList = pageResult.getList();
        CustomFieldDataListReqBO reqBO = CustomFieldDataListReqBO.builder().bizType(BizTypeEnum.PAYROLL.getValue())
                .labels(CollUtil.newArrayList(CustomFieldLabelEnum.PAYROLL_EMPLOYEE_INFO.getValue(), CustomFieldLabelEnum.PAYROLL_DETAIL_INFO.getValue()))
                .recordIds(CollectionUtils.convertList(detailList, PayrollApproveRecordDetailDO::getId)).edition(BizTypeEnum.PAYROLL_APPROVAL.getValue())
                .version(PayrollStateEnum.ARCHIVE.getValue().equals(payroll.getState())? payroll.getId(): 0).build();
        Map<Long, List<CustomFieldDataRespBO>> fieldDataMap = CollectionUtils.convertMultiMap(
                customFieldDataService.getDataList(reqBO), CustomFieldDataRespBO::getRecordId);
        Map<Long, EmployeeDO> employeeMap = CollectionUtils.convertMap(employeeService.getEmployeeList(
                CollectionUtils.convertList(detailList, PayrollApproveRecordDetailDO::getEmployeeId)), EmployeeDO::getId);
        List<CustomFieldDataRespBO> respBOs = new ArrayList<>();
        detailList.forEach(detail -> {
            Map<String, Object> detailMap = BeanUtil.beanToMap(detail);
            if(employeeMap.containsKey(detail.getEmployeeId())){
                EmployeeDO employee = employeeMap.get(detail.getEmployeeId());
                detailMap.put("employeeNo", employee.getEmployeeNo());
                detailMap.put("employeeDeptId", employee.getDeptId());
                detailMap.put("employeePostId", employee.getPostId());
                detailMap.put("employeePostLevelId", employee.getPostLevelId());
                detailMap.put("employeeState", EmployeeStatusEnum.getName(employee.getState()));
            }
            respBOs.addAll(CollectionUtils.convertList(fieldDataMap.get(detail.getId()), fieldData -> {
                String key = StringUtils.underlineToCamel(fieldData.getColName());
                if(detailMap.containsKey(key)){
                    fieldData.setFieldValue(Objects.toString(detailMap.get(key)));
                }
                return fieldData;
            }));
        });
        List<CustomFieldRespDTO> fieldRespDTOs = CollectionUtils.filterList(customFieldServiceProvider.getFieldList(
                CustomFieldReqDTO.builder().bizType(BizTypeEnum.PAYROLL.getValue())
                        .labels(Collections.singletonList(CustomFieldLabelEnum.PAYROLL_DETAIL_INFO.getValue()))
                        .version(PayrollStateEnum.ARCHIVE.getValue().equals(payroll.getState()) ? payroll.getId() : 0).build()),
                field -> CustomFieldTypeEnum.NUMBER.getValue().equals(field.getType()));
        List<PayrollApproveRecordDetailDO> allDetailList = payrollApproveRecordDetailService.getDetailByPayrollApproveRecordId(pageReqVO.getPayrollApproveRecordId());
        Map<Long, List<CustomFieldDataRespBO>> map = CollectionUtils.convertMultiMap(customFieldDataService.getDataList(
                CustomFieldDataListReqBO.builder().bizType(BizTypeEnum.PAYROLL.getValue())
                        .labels(Collections.singletonList(CustomFieldLabelEnum.PAYROLL_DETAIL_INFO.getValue()))
                        .recordIds(CollectionUtils.convertList(allDetailList, PayrollApproveRecordDetailDO::getId))
                        .edition(BizTypeEnum.PAYROLL_APPROVAL.getValue())
                        .version(PayrollStateEnum.ARCHIVE.getValue().equals(payroll.getState())? payroll.getId(): 0).build()), CustomFieldDataRespBO::getFieldId);
        List<Map<String, CustomFieldDataRespBO>> respVOList = customFieldDataService.parseData(reqBO, respBOs);
        respVOList.add(CollectionUtils.convertMap(fieldRespDTOs, CustomFieldRespDTO::getColName, field -> {
            CustomFieldDataRespBO respBO = BeanUtil.toBean(field, CustomFieldDataRespBO.class);
            if(!"effective_salary".equals(field.getColName())){
                respBO.setFieldValue(Objects.toString(CollectionUtils.getSumValue(CollectionUtils.filterList(map.get(field.getId()),
                                fieldData -> StrUtil.isNotBlank(fieldData.getFieldValue())),
                        fieldData -> BigDecimal.valueOf(Double.parseDouble(fieldData.getFieldValue().replaceAll("[^0-9.-]",""))), BigDecimal::add, BigDecimal.ZERO)));
            }else {
                respBO.setFieldValue(Objects.toString(CollectionUtils.getSumValue(allDetailList,
                        detail -> BigDecimal.valueOf(Double.parseDouble(detail.getEffectiveSalary().replaceAll("[^0-9.-]",""))), BigDecimal::add, BigDecimal.ZERO)));
            }
            return respBO;
        }));
        return success(new PageResult<>(respVOList, pageResult.getTotal()));
    }

}